﻿/* =====================================================================================================
* FileName: TSCPrinter            
* Created By: 马志
* Created Date: 2016年1月7日
* Email：hautmz@163.com
* Modified By:
* Modified Date:
* Copyright (c) 2010 - 2015 北京其乐融融科技有限公司
* ===================================================================================================== */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using QlrrPrintService.Common;
using QlrrPrintService.Common.Command;
using Newtonsoft.Json;
using System.Collections.Specialized;
using System.Threading;
using PluginBase;

namespace QlrrPrintService.Print
{
    public class TSCPrinter : IPrinter,IDisposable
    {
        #region 静态方法

        [DllImport("TSCLIB.dll", EntryPoint = "about")]
        public static extern int about();
        [DllImport("TSCLIB.dll", EntryPoint = "Usbrestart")]
        public static extern int usbrestart();

        [DllImport("TSCLIB.dll", EntryPoint = "openport")]
        public static extern int openport(string printername);

        [DllImport("TSCLIB.dll", EntryPoint = "barcode")]
        public static extern int barcode(string x, string y, string type,
                    string height, string readable, string rotation,
                    string narrow, string wide, string code);

        [DllImport("TSCLIB.dll", EntryPoint = "clearbuffer")]
        public static extern int clearbuffer();

        [DllImport("TSCLIB.dll", EntryPoint = "closeport")]
        public static extern int closeport();

        [DllImport("TSCLIB.dll", EntryPoint = "downloadpcx")]
        public static extern int downloadpcx(string filename, string image_name);

        [DllImport("TSCLIB.dll", EntryPoint = "formfeed")]
        public static extern int formfeed();

        [DllImport("TSCLIB.dll", EntryPoint = "nobackfeed")]
        public static extern int nobackfeed();

        [DllImport("TSCLIB.dll", EntryPoint = "printerfont")]
        public static extern int printerfont(string x, string y, string fonttype,
                        string rotation, string xmul, string ymul,
                        string text);

        [DllImport("TSCLIB.dll", EntryPoint = "printlabel")]
        public static extern int printlabel(string set, string copy);

        [DllImport("TSCLIB.dll", EntryPoint = "sendcommand")]
        public static extern int sendcommand(string printercommand);

        [DllImport("TSCLIB.dll", EntryPoint = "setup")]
        public static extern int setup(string width, string height,
                  string speed, string density,
                  string sensor, string vertical,
                  string offset);

        [DllImport("TSCLIB.dll", EntryPoint = "windowsfont")]
        public static extern int windowsfont(int x, int y, int fontheight,
                        int rotation, int fontstyle, int fontunderline,
                        string szFaceName, string content);
        [DllImport("TSCLIB.dll", EntryPoint = "usbportqueryprinter")]
        public static extern int usbportqueryprinter();

        [DllImport("TSCLIB.dll", EntryPoint = "sendBinaryDataNoCRLF")]
        public static extern void sendBinaryDataNoCRLF(byte[] data, int len);

        

        #endregion

        #region 构造函数

        public TSCPrinter()
        {
            _printerStateNameValueCollection = Util.ConvertEnumDescriptionValue(typeof(PrinterState));
        }

        #endregion

        #region 变量

        protected string _printId = "";
        protected int _pageHeight;
        protected int _pageWidth;

        protected int _printSpeed = 2;

        protected Cls _cls = new Cls();

        protected PrinterPortState _printerState = PrinterPortState.Closed;

        protected NameValueCollection _printerStateNameValueCollection = new NameValueCollection();

        #endregion

        #region IPrint

        public event OnCommandExquteCompleteHander OnCommandExcuteComplete;

        public void OpenPrinter(string printerName)
        {
            DoOpenPrinter(printerName);
            
        }

        public void ClosePrintert()
        {
            DoClosePrinter();
        }

        public int QueryState(PluginRequestMessage pluginMessage)
        {
            //if (_printerState != PrinterPortState.Opened)
            //{
                OpenPrinter("USB");
            //}
            int state=DoQueryPrinterState();
            HandQueryState(state, pluginMessage);
            ClosePrintert();
            return state;
        }

        public void Print(PluginRequestMessage pluginMessage)
        {
            if (pluginMessage != null)
            {
                List<PrintPaper> printPapers = null;
                try
                {
                    printPapers = JsonConvert.DeserializeObject<List<PrintPaper>>(pluginMessage.MessageBody);
                }
                catch(Exception ex)
                {
                }
                if (printPapers != null)
                {
                    //if (_printerState != PrinterPortState.Opened)
                        OpenPrinter("USB");
                    int result = -1;
                    int total = 0;
                    int successCount = 0;
                    List<string> errorIds = new List<string>();
                    foreach (var item in printPapers)
                    {
                        total++;
                        result = OnReceivePrintMessage(item);
                        if (result > 0)
                        {
                            successCount++;
                        }
                        else
                        {
                            errorIds.Add(item.Id);
                        }
                    }
                    ClosePrintert();
                    Thread.Sleep(100);
                    HandPrintComplete(pluginMessage,total, successCount, errorIds);
                    
                }
            }
        }

        public void Restet(PluginRequestMessage pluginMessage)
        {
            HandRestart(pluginMessage);
        }

        public int SendCommand(PluginRequestMessage pluginMessage)
        {
            var result = DoSendCommand(pluginMessage);
            HandSendCommandComplete(pluginMessage,result);
            return result;
        }

        #endregion

        #region 受保护的方法

        protected virtual int DoSendCommand(PluginRequestMessage pluginMessage)
        {
            var result = sendcommand(pluginMessage.MessageBody);
                 
            return result;
        }

        protected virtual void HandSendCommandComplete(PluginRequestMessage message, int result)
        {
            if (OnCommandExcuteComplete != null)
            {
                string msg = "";
                if (result == 1)
                {
                    msg = "Success";
                }
                else
                {
                    msg = "Fail";
                }
                OnCommandExcuteComplete(this, PluginMessageType.SendOtherCommand,message.SourceId, msg);
            }
            
        }


        protected virtual int DoQueryPrinterState()
        {
            try
            {
                return usbportqueryprinter();
            }
            catch (Exception e)
            {
                return -1;
            }
            
        }

        protected virtual void DoOpenPrinter(string printerName)
        {
            if (string.IsNullOrEmpty(printerName))
            {
                printerName = "USB";
            }
            //if (PrinterPortState.Closed == _printerState)
            //{
                try
                {
                    DoClosePrinter();
                    _printerState = (PrinterPortState)openport(printerName);
                }
                catch
                { }
                
            //}
        }

        protected virtual void DoClosePrinter()
        {
            if (closeport() == 1)
            {
                _printerState = PrinterPortState.Closed;
            }
        }

        protected virtual void HandPrintComplete(PluginRequestMessage message,int total, int success, List<string> errorIds) 
        {
            PrintCompleteEventArgs args = new PrintCompleteEventArgs();
            args.TotalCount = total;
            args.SuccessedCount = success;
            args.ErrorId = errorIds;
            args.SourceId = message.SourceId;
            if (OnCommandExcuteComplete != null)
            {
                OnCommandExcuteComplete(this, PluginMessageType.PrintComplete,message.SourceId, Newtonsoft.Json.JsonConvert.SerializeObject(args));
            }
        }

        protected virtual int OnReceivePrintMessage(PrintPaper printPaper)
        {
            //var r=setup("35", "20", "4", "8", "0", "0", "0");  
            int result = -1;

            

            result = PrintTemplate(printPaper);
            if (result == -1)
            {
                return -1;
            }

            result = PrintBarcode(printPaper);

            result = PrintFonts(printPaper);

            result = PrintLines(printPaper);

            PrintQRCode(printPaper);

            result = printlabel("1", "1");

            return result;
            

        }

        protected virtual int PrintLines(PrintPaper printPaper)
        {
            int result = -1;
            if (printPaper.PriltLines != null)
            {
                foreach (var item in printPaper.PriltLines)
                {
                    result = sendcommand(item.ToTSPLCommandAscii(printPaper.Mm_to_dpi));
                }
            }
            return result;
        }

        protected virtual void PrintQRCode(PrintPaper printPaper)
        {
            if (printPaper.PrintQRCodes != null)
            {
                foreach (var item in printPaper.PrintQRCodes)
                {
                    var data=item.ToTSPLCommandByte(1);
                    sendBinaryDataNoCRLF(data, data.Length);
                }
            }
        }

        protected virtual int PrintFonts(PrintPaper printPaper)
        {
            int result = -1;
            if (printPaper.PrintFonts != null)
            {
                foreach (var item in printPaper.PrintFonts)
                {
                    result=windowsfont(item.X,
                        item.Y,
                        item.Fontheight,
                        item.Rotation,
                        item.Fontstyle,
                        item.Fontunderline,
                        item.SzFaceName,
                        item.Content);
                }
            }
            return result;
        }

        protected virtual int PrintBarcode(PrintPaper printPaper)
        {
            int result = -1;
            if (printPaper.PrintBarCodes != null)
            {
                foreach (var item in printPaper.PrintBarCodes)
                {
                    result=barcode(item.X.ToString(),
                        item.Y.ToString(),
                        item.BarcodeType,
                        item.BarcodeHeight.ToString(),
                        item.IsPrintBarcodeFont.ToString(),
                        item.Rotation.ToString(),
                        item.Narrow.ToString(),
                        item.Wide.ToString(),
                        item.Code);
                }
            }
            return result;
        }

        protected virtual int PrintTemplate(PrintPaper printPaper)
        {
            int result = -1;
            if (printPaper.PrintPaperTemplate == null && printPaper.PrintPaperTemplateId != null)
            {
                printPaper.PrintPaperTemplate = PrintTemplateManager.Instance.GetPrintPaperTemplate(printPaper.PrintPaperTemplateId);
            }

            if (printPaper.PrintPaperTemplate != null)
            {
                var commandHead = printPaper.
                        PrintPaperTemplate.ToTSPLCommandAscii(printPaper.Mm_to_dpi);
                if (commandHead != null)
                {
                    result = sendcommand(commandHead);
                }

                var commandLines = printPaper.PrintPaperTemplate.PriltLines;
                if (commandLines != null)
                {
                    foreach (var item in commandLines)
                    {
                        result = sendcommand(item.ToTSPLCommandAscii(printPaper.Mm_to_dpi));
                    }
                    
                }

                var commandPrintBitmap = printPaper.PrintPaperTemplate.PrintBitmaps;
                if (commandPrintBitmap != null)
                {
                    foreach (var item in commandPrintBitmap)
                    {
                        var data = item.ToTSPLCommandByte(printPaper.Mm_to_dpi);
                        if (data != null)
                        {
                            sendBinaryDataNoCRLF(data, data.Length);
                        }
                        
                    }
                }

                var qrcodes = printPaper.PrintPaperTemplate.PrintQRCodes;
                if (qrcodes != null)
                {
                    foreach (var item in qrcodes)
                    {
                        var data = item.ToTSPLCommandByte(printPaper.Mm_to_dpi);
                        sendBinaryDataNoCRLF(data, data.Length);
                        //sendcommand(item.ToTSPLCommandAscii(printPaper.Mm_to_dpi));
                    }
                }
            }
            return result;
        }

        protected virtual void OnBeforePrint()
        {
 
        }

        protected virtual int HandQueryState(int state,PluginRequestMessage pluginMessage)
        {
            PrinterStateMessage message = new PrinterStateMessage();
            var kv = _printerStateNameValueCollection.Get(((PrinterState)state).ToString());
            if (kv != null)
            {
                message.Des = kv;
                message.PrinterState = (PrinterState)state;
            }
            else
            {
                message.Des = _printerStateNameValueCollection.Get(PrinterState.UnKnown.ToString());
                message.PrinterState = PrinterState.UnKnown;
            }
            if (OnCommandExcuteComplete != null)
            {
                OnCommandExcuteComplete(this,PluginMessageType.QueryState,pluginMessage.SourceId, Newtonsoft.Json.JsonConvert.SerializeObject(message));
            }
            return (int)message.PrinterState;

        }

        protected virtual void HandRestart(PluginRequestMessage pluginMessage)
        {
            var resetCommand = new ResetCommand();
            var data=resetCommand.ToTSPLCommandByte(1);
            for (int i = 0; i < 4; i++)
            {
                sendBinaryDataNoCRLF(data, data.Length);
                Thread.Sleep(2000);
            }
            
            while (true)
            {
                Thread.Sleep(2000);
                var state = (PrinterState)DoQueryPrinterState();
                if (state == PrinterState.Waiting ||
                    state == PrinterState.Printing)
                {
                    break;
                }

            }
        }

        

        #endregion

        #region IDispose
       

        public void Dispose()
        {
            ClosePrintert();
        }

        #endregion

      
    }
}
